import { Node } from "cc";
import { InjectableObject } from "../../inject";
import { ViewMakerProvider } from "../../inject/provider/ViewMakerProvider";
import { IViewMap } from "../base/IViewMap";

export const View_Name_Tag = '__View_Name__';

export const View_Factory_Adapter_Tag = '__View_Factory_Adapter__';

export interface IViewFactory {
    createViewByResourceId(resPath: string, viewName: string);
}

export class ViewMap extends InjectableObject implements IViewMap {

    mapViewRes(viewName, resPath) {
        this.mapViewCreator(viewName, () => {
            let viewFactory: IViewFactory = this.injector.getInstance(View_Factory_Adapter_Tag);
            if (viewFactory) {
                return viewFactory.createViewByResourceId(resPath, viewName);
            } else {
                return null;
            }
        })
    }

    unmapView(viewName) {
        this.injector.unmap(viewName);
    }

    hasView(viewName): boolean {
        return this.injector.hasMapping(viewName);
    }

    mapViewCreator(viewName: string, viewCreator) {
        let provider = new ViewMakerProvider(this.wrappedCreator(viewName, viewCreator));
        this.injector.mapCustomRule(viewName, provider);
    }

    private wrappedCreator(name: string, creator: Function) {
        return async () => {
            let view: Node = await creator();
            if (view) {
                // Reflect.defineProperty(view, '__View_Name__', { value : name });

                Object.defineProperty(view, View_Name_Tag, {
                    value: name,
                    writable: false,
                    configurable: false,
                    enumerable: false
                })
            }

            return view;
        }
    }
}